/**
 * 
 */
package com.ra.landlord;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.da.landlord.DaChargeBillRecordService;
import com.da.landlord.DaChargeItem;
import com.da.landlord.DaFeeRule;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.system.Version;

/**
 * 费用描述服务
 * @author colin
 * @date 2014年9月14日
 */
@Service
public class FeeRuleCfgDescService {
	
	private final static Log logger = LogFactory.getLog(FeeRuleCfgDescService.class);
	
	@Resource
	private GenericService genericService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private FeeRuleCfgService feeRuleCfgService;
	
	@Resource
	private FeeRecordService feeRecordService;
	
	@Resource
	private DaChargeBillRecordService chargeBillRecordService;
	/**
	 * 获取费用描述
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public FeeRuleCfgDesc view(FeeRuleCfgDesc model, Integer feeRuleCfgId){
		return genericService.load(model);
	}
	
	/**
	 * 获取费用描述
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public FeeRuleCfgDesc get(FeeRuleCfgDesc model){
		FeeRuleCfgDesc desc = genericService.load(model);
		if (desc == null) {
			desc = new FeeRuleCfgDesc();
		}
		return desc;
	}
	
	/**
	 * 查询固定费用列表
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDesc> searchFixed(){
		FeeRuleCfgDesc model = new FeeRuleCfgDesc();
		model.setStatus(Version.STATUS_VALID);
		model.setType(FeeRuleType.fixed);
		PageInfo<FeeRuleCfgDesc> pageInfo = genericService.search(model, 0, 1000, null, null, false, null, null, true, false);
		return pageInfo.getData();
	}
	
	/**
	 * 查询仪表费用列表
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDesc> searchMeter(){
		FeeRuleCfgDesc model = new FeeRuleCfgDesc();
		model.setStatus(Version.STATUS_VALID);
		model.setType(FeeRuleType.meter);
		PageInfo<FeeRuleCfgDesc> pageInfo = genericService.search(model, 0, 1000, null, null, false, null, null, true, false);
		return pageInfo.getData();
	}
	
	/**
	 * 查询公摊的仪表费用列表
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDesc> searchShareMeter(){
		FeeRuleCfgDesc model = new FeeRuleCfgDesc();
		model.setStatus(Version.STATUS_VALID);
		model.setType(FeeRuleType.meter);
		model.setIsShare(true);
		PageInfo<FeeRuleCfgDesc> pageInfo = genericService.search(model, 0, 1000, null, null, false, null, null, true, false);
		return pageInfo.getData();
	}
	
	/**
	 * 查询仪表费用列表
	 * @param model
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDesc> searchAllDesc(FeeRuleCfgDesc model){
		model.setStatus(Version.STATUS_VALID);
		PageInfo<FeeRuleCfgDesc> pageInfo = genericService.search(model, 0, 1000, "type", null, false, null, null, true, false);
		return pageInfo.getData();
	}
	
	/**
	 * 查询仪表费用列表: 改造计费项，一种计费方式对应一个计费描述
	 * @param model
	 * @return
	 * @see V4.0
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDescVO> searchAllFeeDesc(FeeRuleCfgDesc model)
	{
		QLInfo qlInfo = new QLInfo("select a from " + FeeRuleCfgDesc.class.getName() + " a where a.status = ? and a.landlordUser = ?", false);
		qlInfo.addParam(Version.STATUS_VALID);
		qlInfo.addParam(landlordUserService.getLandlordOwnerUser());
		List<FeeRuleCfgDescVO> result = new ArrayList<FeeRuleCfgDescVO>();
		
		// 得到feeRuleCfgDesc 数据
		List<FeeRuleCfgDesc> feeRuleCfgDescList = genericService.searchByQl(qlInfo).getData();
		for (FeeRuleCfgDesc feeDesc : feeRuleCfgDescList) 
		{
			/*if (feeDesc.getFeeRuleCfgs().size() > 1)
			{
				System.out.println("feeDesc.getFeeRuleCfgs().size ==>:" + feeDesc.getFeeRuleCfgs().size());
				for (FeeRuleCfg cfg : feeDesc.getFeeRuleCfgs()) 
				{
					System.out.println("cfg.calc.id=>" + cfg.getFeeRuleCfgCalc().getId() + "|price=>" + cfg.getFeeRuleCfgCalc().getPrice());
				}
			}*/
			
			int index = 1;
			for (FeeRuleCfg feeRuleCfg : feeDesc.getFeeRuleCfgs()) 
			{
				FeeRuleCfgDescVO vo = new FeeRuleCfgDescVO();
				vo.setId(feeDesc.getId() + "_" + feeRuleCfg.getId());
				vo.setName(feeDesc.getName());
				vo.setCalcMode(feeDesc.getCalcMode());
				vo.setType(feeDesc.getType());
				vo.setUnit(feeDesc.getUnit());
				
				if (StringUtils.isNotEmpty(feeRuleCfg.getFeeRuleCfgCalc().getDescription()))
				{
					vo.setDescription(feeRuleCfg.getFeeRuleCfgCalc().getDescription());
				}
				else
				{
					vo.setDescription(feeDesc.getDescription());
				}
				
				vo.setPrice(feeRuleCfg.getFeeRuleCfgCalc().getPrice());
				
				result.add(vo);
				
				index++;
			}
		}

		return result;
	}
	
	/**
	 * 新增费用描述
	 * @param model
	 * @return
	 */
	@Rest(type = "add")
	public FeeRuleCfgDesc addFeeRuleCfgDesc(FeeRuleCfgDesc model){
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		if (model.getIsShare() == null) {
			model.setIsShare(false);
		}
		
		if (FeeRuleType.fixed.equals(model.getType()))
		{
			model.setUnit("");
		}
		
		model.setLandlordUser(landlordUser.getOwnerUser());
		return genericService.add(model);
	}
	
	/**
	 * 新增收费项及计费方式（DA）
	 * @param feeRuleCfg
	 * @return
	 */
	@Transactional
	@Rest(type = "add")
	public FeeRuleCfgDesc addDescAndFeeRuleCfg(FeeRuleCfgDesc model){
		//FeeRuleCfg feeRuleCfg = null;
		List<FeeRuleCfg> resultFeeRuleCfgs = new ArrayList<>();
		FeeRuleCfgDesc feeRuleCfgDesc = addFeeRuleCfgDesc(model);
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		List<FeeRuleCfg> feeRuleCfgs = model.getFeeRuleCfgs();
		if (feeRuleCfgs != null && feeRuleCfgs.size() > 0) {
			for (FeeRuleCfg feeRuleCfg : feeRuleCfgs) {
				//默认规则有效0
				feeRuleCfg.setType(0);
				feeRuleCfg.setFeeRuleCfgDesc(feeRuleCfgDesc);
				feeRuleCfg.setLandlordUser(landlordUser.getOwnerUser());
				
				FeeRuleCfgCalc feeRuleCfgCalc = feeRuleCfg.getFeeRuleCfgCalc();
				feeRuleCfgCalc.setLandlordUser(landlordUser.getOwnerUser());
				//出租周期类型：0 - 月， 1 - 日 (暂未用)
				feeRuleCfgCalc.setRentCycleType(0);
				//阶梯计算，暂时没用
				feeRuleCfgCalc.setType(0);
				feeRuleCfgCalc.setPrice(feeRuleCfgCalc.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
				FeeRuleCfg tempFeeRuleCfg = genericService.add(feeRuleCfg);
				resultFeeRuleCfgs.add(tempFeeRuleCfg);
			}
		}
		feeRuleCfgDesc.setFeeRuleCfgs(resultFeeRuleCfgs);
		return feeRuleCfgDesc;
		
	}
	
	/**
	 * 逻辑删除费用描述，目前仅大房东APP使用
	 * @param model
	 * @return
	 */
	@Rest(type="delete")
	public boolean deleteFeeRuleCfgDesc(List<Object> model) {
		if (model != null) {
			for (int i = 0; i < model.size(); i++) {
				FeeRuleCfgDesc feeRuleCfgDesc = (FeeRuleCfgDesc)model.get(i);
				if (feeRuleCfgDesc != null) {
					feeRuleCfgDesc = genericService.load(FeeRuleCfgDesc.class,
							feeRuleCfgDesc.getId());
					if (feeRuleCfgDesc != null) {
						feeRuleCfgDesc.setStatus(Version.STATUS_INVALID);
						genericService.update(feeRuleCfgDesc);
					}
				}
			}
		}
		return true;
	}
	
	/**
	 * 检查计费项规则是否被使用
	 * @param lstFeeRuleCfg
	 * @return
	 */
	public boolean checkFeeRuleCfgsUsedByRoom(List<FeeRuleCfg> lstFeeRuleCfg)
	{
		boolean isUsed = false;
		if (lstFeeRuleCfg == null || lstFeeRuleCfg.isEmpty())
		{
			return isUsed;
		}
		
		for (FeeRuleCfg feeRuleCfg : lstFeeRuleCfg)
		{
			if (checkFeeRuleCfgUsedByRoom(feeRuleCfg))
			{
				isUsed = true;
				break;
			}
		}
		
		return isUsed;
	}
	
	/**
	 * 检查计费项规则是否被使用(包括集中式和/分散式的检查/房屋附加费/房屋附加费记录)
	 * @param feeRuleCfg
	 * @return
	 * @since v4.0
	 */
	public boolean checkFeeRuleCfgUsedByRoom(FeeRuleCfg feeRuleCfg)
	{
		boolean isUsed = false;
		if (feeRuleCfg == null)
		{
			return isUsed;
		}
		
		//集中式房间是否使用: FeeRule
		isUsed = checkFeeRuleCfgUsed(FeeRule.class, feeRuleCfg.getId());
		if (!isUsed)
		{
			//分散式房源是否使用: DaFeeRule
			isUsed = checkFeeRuleCfgUsed(DaFeeRule.class, feeRuleCfg.getId());
		}
		if (!isUsed)
		{
			//房屋附加费: FeeAddition
			isUsed = checkFeeRuleCfgUsed(FeeAddition.class, feeRuleCfg.getId());
		}
		if (!isUsed)
		{
			//房屋附加费记录: FeeAdditionRecord
			isUsed = checkFeeRuleCfgUsed(FeeAdditionRecord.class, feeRuleCfg.getId());
		}
		
		if (!isUsed)
		{
			//房屋附加费记录: DaChargeItem
			isUsed = checkFeeRuleCfgUsed(DaChargeItem.class, feeRuleCfg.getId());
		}
		
		return isUsed;
	}
	
	/**
	 * 检查是否使用了计费项
	 * @param clazz
	 * @param feeRuleCfgId
	 * @return
	 */
	private boolean checkFeeRuleCfgUsed(Class clazz, Integer feeRuleCfgId)
	{
		QLInfo ql = new QLInfo("from " + clazz.getName() + " a where a.feeRuleCfg.id = ?", true, feeRuleCfgId);
		int count = genericService.getCount(ql, false);
		return (count > 0);
	}
	
	@Transactional
    @Rest(type="update")
	public FeeRuleCfgDesc updateFeeRuleCfgDesc(FeeRuleCfgDesc model) {
		return genericService.update(model);
	}
	
	/**
	 * 更新收费项，包含新增计费方式
	 * @param model
	 * @return
	 */
	@Transactional
    @Rest(type="update")
	public FeeRuleCfgDesc updateDescAndFeeRuleCfg(FeeRuleCfgDesc model) {
		
		Collection<String> enableFields = Arrays.asList("name", "type", "description", "initialValue", "lossValue", "calcMode"
				, "unit", "feeRuleCfgs.feeRuleCfgCalc.description", "feeRuleCfgs.feeRuleCfgCalc.price", "feeRuleCfgs.feeRuleCfgCalc.valueLow"
				, "feeRuleCfgs.feeRuleCfgCalc.rentCycle");
		FeeRuleCfgDesc feeRuleCfgDesc = genericService.update(model, false, enableFields, null);
		
		LandlordUser landlordUser = genericService.load(landlordUserService.getLoginUser());
		List<FeeRuleCfg> feeRuleCfgs = model.getFeeRuleCfgs();
		List<FeeRuleCfg> addFeeRuleCfgs = new ArrayList<>();
		if (feeRuleCfgs != null && feeRuleCfgs.size() > 0) {
			for (FeeRuleCfg feeRuleCfg : feeRuleCfgs) {
				
				if (feeRuleCfg.getId() == null) {
					
					feeRuleCfg.setFeeRuleCfgDesc(model);
					feeRuleCfg.setLandlordUser(landlordUser.getOwnerUser());
					feeRuleCfg.setStatus(1);
					feeRuleCfg.setType(0);
					feeRuleCfg.setVersion(Version.STATUS_VALID);
					
					FeeRuleCfgCalc feeRuleCfgCalc = feeRuleCfg.getFeeRuleCfgCalc();
					feeRuleCfgCalc.setLandlordUser(landlordUser.getOwnerUser());
					feeRuleCfgCalc.setRentCycleType(0);
					feeRuleCfgCalc.setStatus(1);
					feeRuleCfgCalc.setType(0);
					feeRuleCfgCalc.setVersion(Version.STATUS_VALID);
					feeRuleCfg = genericService.add(feeRuleCfg);
					addFeeRuleCfgs.add(feeRuleCfg);
				}
				
			}
		}
		feeRuleCfgDesc.getFeeRuleCfgs().addAll(addFeeRuleCfgs);
		return feeRuleCfgDesc;
	}
	
	/**
	 * 更新收费项和计费方式
	 * @param model
	 * @return
	 * @since v4.0
	 */
	@Transactional
	public Boolean updateDescAndSingleFeeRuleCfg(FeeRuleCfgDesc model) 
	{
		FeeRuleCfgDesc queryModel = new FeeRuleCfgDesc();
		queryModel.setId(model.getId());
		FeeRuleCfgDesc feeDescDb = genericService.load(queryModel, false);
		feeDescDb.setName(model.getName());
		if (FeeRuleType.fixed.equals(model.getType()))
		{
			feeDescDb.setUnit("");
		}
		else
		{
			feeDescDb.setUnit(model.getUnit());
		}
		feeDescDb.setCalcMode(model.getCalcMode());
		feeDescDb.setType(model.getType());
		feeDescDb.setDescription(model.getDescription());
		genericService.merge(feeDescDb);
		
		FeeRuleCfg requestFeeRuleCfg = model.getFeeRuleCfgs().get(0);
		
		FeeRuleCfg queryCfgModel = new FeeRuleCfg();
		queryCfgModel.setId(requestFeeRuleCfg.getId());
		FeeRuleCfg dbFeeRuleCfg = genericService.load(queryCfgModel, false);
		if (dbFeeRuleCfg.getFeeRuleCfgCalc().getPrice().compareTo(requestFeeRuleCfg.getFeeRuleCfgCalc().getPrice()) != 0) {
			//修改已经产生费用的价格
			feeRecordService.repaireFeeRecordWhenFeeRuleCfgPriceChanged(dbFeeRuleCfg, requestFeeRuleCfg.getFeeRuleCfgCalc().getPrice());
			chargeBillRecordService.repaireChargeBillRecordWhenFeeRuleCfgPriceChanged(dbFeeRuleCfg, requestFeeRuleCfg.getFeeRuleCfgCalc().getPrice());
		}
		dbFeeRuleCfg.getFeeRuleCfgCalc().setPrice(requestFeeRuleCfg.getFeeRuleCfgCalc().getPrice());
		dbFeeRuleCfg.getFeeRuleCfgCalc().setValueLow(requestFeeRuleCfg.getFeeRuleCfgCalc().getValueLow());
		dbFeeRuleCfg.getFeeRuleCfgCalc().setRentCycle(requestFeeRuleCfg.getFeeRuleCfgCalc().getRentCycle());
		genericService.merge(dbFeeRuleCfg);
		return true;
	}
	
	@Transactional
    @Rest(type="update")
	public FeeRuleCfgDesc deleteDescAndFeeRuleCfg(FeeRuleCfgDesc model) {
		return null;
	}
}
